<script setup lang="ts" name="BaseEchart">
import {
  computed,
  PropType,
  ref,
  unref,
  watch,
  onMounted,
  onBeforeUnmount,
  onActivated,
  nextTick
} from 'vue'
import type { EChartsOption } from 'echarts'
import echarts from '@/plugins/echarts'
// import "echarts-liquidfill";
import { debounce, isString, merge, isArray, isObject } from 'lodash-es'
import { propTypes } from '@/utils/prop-types'


const props = defineProps({
  options: {
    type: Object as PropType<EChartsOption>,
    required: true
  },
  width: propTypes.oneOfType([Number, String]).def(''),
  // 传入height 自适应配置
  height: propTypes.oneOfType([Number, String]).def(200),
  loading: {
    type: Boolean,
    default: false
  }, // 数据加载提示
  showNoData: {
    type: Boolean,
    default: true
  } // 是否显示空数据提示
})

const elRef = ref<ElRef>()
const contentEl = ref<Element>()
const tempEchartRef: any = ref()
const noData = ref(false) // 图表无数据
let echartRef: Nullable<echarts.ECharts> = null // 这里使用响应式会导致tooltip失效。

const styles = computed(() => {
  const width = isString(props.width) ? props.width : `${props.width}px`
  const height = isString(props.height) ? window.innerHeight / 1080 * (props.height as any) as number + 'px' : `${props.height}px`

  return {
    width,
    height
  }
})

const checkNoData = (options: any) => {
  if (!props.showNoData) {
    return false
  }
  let dataLen = 0
  if (options.series) {
    if (isArray(options.series)) {
      options.series.forEach((seriesItem: any) => {
        if (seriesItem.data && seriesItem.data.length) {
          dataLen += seriesItem.data.length
        }
      })
    } else if (isObject(options.series)) {
      if (options.series.data && options.series.data.length) {
        dataLen += options.series.data.length
      }
    }
  }
  noData.value = dataLen === 0
  return dataLen === 0
}

const initChart = () => {
  if (unref(elRef) && props.options) {
    const initOptions = merge(
      // 初始化图表默认配置
      {
        grid: { containLabel: true },
        color: ['#4385F4', '#38CB89', '#FEC400', '#FF6A3C', '#F34242', '#3847CC']
      },
      // 自定义图表配置
      props.options
    )
    tempEchartRef.value = echartRef = echarts.init(unref(elRef) as HTMLElement)
    echartRef?.setOption(unref(initOptions))

    // 初始化图表，检验是否有数据
    nextTick(() => {
      checkNoData(initOptions)
    })
  }
}



watch(
  () => props.options,
  (newOptions: any) => {
    echartRef?.setOption(newOptions)
    setTimeout(() => {
      checkNoData(newOptions)
    })
  },
  { deep: true }
)

const resizeHandler = debounce(() => {
  if (echartRef) {
    echartRef.resize()
  }
}, 100)

const contentResizeHandler = async (e: TransitionEvent) => {
  if (e.propertyName === 'width') {
    resizeHandler()
  }
}

onMounted(() => {
  initChart()
  window.addEventListener('resize', resizeHandler)
  contentEl.value = document.getElementsByClassName('layout-sidebar')[0]
  unref(contentEl) &&
    (unref(contentEl) as any).addEventListener('transitionend', contentResizeHandler)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeHandler)
  unref(contentEl) &&
    (unref(contentEl) as any).removeEventListener('transitionend', contentResizeHandler)
})

onActivated(() => {
  if (echartRef) {
    echartRef.resize()
  }
})

defineExpose({
  echartRef: tempEchartRef
})
</script>

<template>
  <div v-loading="loading" class="base-echart-container">
    <div v-show="!noData" ref="elRef" :class="$attrs.class" :style="styles" />
    <el-empty v-show="showNoData && noData && !loading" :image-size="100" description="暂无数据" />
  </div>
</template>

<style lang="scss" scoped>
.base-echart-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
}
</style>
